package com.shenhaofeng.app.log;

import android.app.Application;
import android.support.annotation.CallSuper;

import com.shenhaofeng.app.device.DeviceInfo;
import com.shenhaofeng.app.utils.io.FileUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * {@link GlobalErrorHandler}的一个实现,将错误保存在文件中
 * Created by Administrator on 2016/10/12.
 */
public class CaptureErrorFileHandler extends GlobalErrorHandler {

    //错误捕获目录
    private File errorDir;

    private boolean filterDefaultUncaughtException = false;


    public CaptureErrorFileHandler(Application application, File errorDir) {
        super(application);
        this.errorDir = errorDir;
        checkDir();

    }


    /**
     * 创建一个默认路径的日志记录地址
     *
     * @param application
     */
    public CaptureErrorFileHandler(Application application) {
        this(application, getDefaultDir(application));
    }


    @CallSuper
    @Override
    protected void uncaughtException(Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Thread t, Throwable e) {
        if (ensureDir()) {
            String deviceInfoString = DeviceInfo.toDeviceInfoString();
            String threadName = t.getName();
            String throwableMessage = e.getMessage();
            String throwableString = obtainThrowableString(e);
            String throwableText = String.format("DeviceInfo:\n\n" +
                            "%s" +
                            "\n\n==============================\n\n" +
                            "thread:%s" +
                            "\n\n==============================\n\n" +
                            "message:\n\n%s" +
                            "\n\n==============================\n\n" +
                            "throwable:\n\n%s"
                    , deviceInfoString, threadName, throwableMessage, throwableString);
            File file = new File(errorDir, String.format("%s-%s.throwable.log", SimpleDateFormat.getDateInstance().format(new Date())
                    , System.currentTimeMillis()));
            FileUtil.writeTextToFile(file, throwableText);
            if (!filterDefaultUncaughtException) {
                uncaughtExceptionHandler.uncaughtException(t, e);
            }
        }
    }


    /**
     * 设置是否过滤掉系统对奔溃的默认处理，默认情况下不会过滤,仍旧会抛出奔溃弹窗
     *
     * @param filterDefaultUncaughtException
     * @return
     */
    public CaptureErrorFileHandler setFilterDefaultUncaughtException(boolean filterDefaultUncaughtException) {
        this.filterDefaultUncaughtException = filterDefaultUncaughtException;
        return this;
    }


    protected boolean ensureDir() {
        return FileUtil.obtainDir(errorDir);
    }


    /**
     * 清空所有错误日志
     *
     * @return
     */
    @CallSuper
    public long clean() {
        return FileUtil.cleanDir(errorDir);
    }


    protected String obtainThrowableString(Throwable throwable) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        PrintWriter printWriter = new PrintWriter(byteArrayOutputStream);
        throwable.printStackTrace(printWriter);
        printWriter.flush();
        return byteArrayOutputStream.toString();
    }


    /**
     * 检查文件夹是否可用可用
     */
    private void checkDir() {
        if (!errorDir.exists() || !errorDir.isDirectory()) {
            throw new IllegalArgumentException("dir Unavailable ");
        }
    }


    /**
     * 获取默认文件夹爱
     *
     * @param application
     * @return
     */
    private static File getDefaultDir(Application application) {
        File dir = new File(application.getFilesDir(), "exception_log");
        if (dir.exists() && dir.isDirectory()) {
            return dir;
        } else if (!dir.exists()) {
            //noinspection ResultOfMethodCallIgnored
            dir.mkdirs();//内部数据 不检查返回值
            return dir;
        } else {
            int i = 1;
            File newDir;
            do {
                newDir = new File(application.getFilesDir(), String.format("exception_log(%s)", i));
                //noinspection ResultOfMethodCallIgnored
                newDir.mkdirs();
            } while (newDir.exists() && newDir.isDirectory());
            return newDir;
        }
    }
}
